﻿namespace UnityEditor
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Runtime.CompilerServices;
    using UnityEditorInternal;
    using UnityEngine;

    internal class DefaultTreeViewDragging : ITreeViewDragging
    {
        [CompilerGenerated]
        private static Func<TreeView.Node, int> <>f__am$cache3;
        private const double k_DropExpandTimeout = 0.7;
        private const float k_HalfDropBetweenHeight = 2f;
        private DropData m_DropData = new DropData();
        internal HierarchyType m_HierarchyType;
        private TreeView m_TreeView;

        public DefaultTreeViewDragging(TreeView treeView, HierarchyType hierarchyType)
        {
            this.m_TreeView = treeView;
            this.m_HierarchyType = hierarchyType;
        }

        public virtual DragAndDropVisualMode DoDrag(TreeView.Node parentNode, TreeView.Node targetNode, bool perform)
        {
            HierarchyProperty property = new HierarchyProperty(this.m_HierarchyType);
            if ((parentNode == null) || !property.Find(parentNode.instanceID, null))
            {
                property = null;
            }
            if (this.m_HierarchyType == HierarchyType.Assets)
            {
                return InternalEditorUtility.ProjectWindowDrag(property, perform);
            }
            return InternalEditorUtility.HierarchyWindowDrag(property, perform);
        }

        public virtual void DragCleanup(bool revertExpanded)
        {
            if (this.m_DropData != null)
            {
                if ((this.m_DropData.expandedArrayBeforeDrag != null) && revertExpanded)
                {
                    this.RestoreExpanded(new List<int>(this.m_DropData.expandedArrayBeforeDrag));
                }
                this.m_DropData = new DropData();
            }
        }

        public virtual bool DragElement(TreeView.Node targetNode, Rect targetNodeRect)
        {
            bool flag2;
            TreeView.Node parent;
            if (targetNode == null)
            {
                DragAndDrop.visualMode = DragAndDropVisualMode.None;
                if (this.m_DropData != null)
                {
                    this.m_DropData.dropTargetControlID = 0;
                    this.m_DropData.rowMarkerControlID = 0;
                }
                return false;
            }
            bool flag = this.m_TreeView.m_Data.CanBeParent(targetNode);
            Rect rect = targetNodeRect;
            float num = !flag ? (targetNodeRect.height * 0.5f) : 2f;
            rect.yMax += num;
            if ((targetNode != null) && !rect.Contains(Event.current.mousePosition))
            {
                return false;
            }
            if (!flag || (Event.current.mousePosition.y > (targetNodeRect.yMax - num)))
            {
                flag2 = false;
            }
            else
            {
                flag2 = true;
            }
            if (this.m_TreeView.m_Data.IsExpanded(targetNode) && (targetNode.children.Length > 0))
            {
                parent = targetNode;
            }
            else
            {
                parent = targetNode.parent;
            }
            DragAndDropVisualMode none = DragAndDropVisualMode.None;
            if (Event.current.type == EventType.DragPerform)
            {
                if (flag2)
                {
                    none = this.DoDrag(targetNode, targetNode, true);
                }
                if (((none == DragAndDropVisualMode.None) && (targetNode != null)) && (parent != null))
                {
                    none = this.DoDrag(parent, targetNode, true);
                }
                if (none != DragAndDropVisualMode.None)
                {
                    DragAndDrop.AcceptDrag();
                    this.DragCleanup(false);
                    List<UnityEngine.Object> list = new List<UnityEngine.Object>(DragAndDrop.objectReferences);
                    int[] draggedInstanceIDs = new int[list.Count];
                    for (int i = 0; i < list.Count; i++)
                    {
                        draggedInstanceIDs[i] = list[i].GetInstanceID();
                    }
                    this.m_TreeView.NotifyListenersThatDragEnded(draggedInstanceIDs);
                }
                else
                {
                    this.DragCleanup(true);
                    this.m_TreeView.NotifyListenersThatDragEnded(null);
                }
            }
            else
            {
                if (this.m_DropData == null)
                {
                    this.m_DropData = new DropData();
                }
                this.m_DropData.dropTargetControlID = 0;
                this.m_DropData.rowMarkerControlID = 0;
                int nodeControlID = TreeView.GetNodeControlID(targetNode);
                if (nodeControlID != this.m_DropData.lastControlID)
                {
                    this.m_DropData.lastControlID = nodeControlID;
                    this.m_DropData.expandItemBeginTimer = Time.realtimeSinceStartup;
                }
                bool flag3 = (Time.realtimeSinceStartup - this.m_DropData.expandItemBeginTimer) > 0.7;
                if (((targetNode != null) && flag3) && ((targetNode.children.Length > 0) && !this.m_TreeView.m_Data.IsExpanded(targetNode)))
                {
                    if (this.m_DropData.expandedArrayBeforeDrag == null)
                    {
                        this.m_DropData.expandedArrayBeforeDrag = this.GetCurrentExpanded().ToArray();
                    }
                    this.m_TreeView.m_Data.SetExpanded(targetNode, true);
                }
                if (flag2)
                {
                    none = this.DoDrag(targetNode, targetNode, false);
                }
                if (none != DragAndDropVisualMode.None)
                {
                    this.m_DropData.dropTargetControlID = nodeControlID;
                    DragAndDrop.visualMode = none;
                }
                else if ((targetNode != null) && (parent != null))
                {
                    none = this.DoDrag(parent, targetNode, false);
                    if (none != DragAndDropVisualMode.None)
                    {
                        this.m_DropData.rowMarkerControlID = nodeControlID;
                        this.m_DropData.dropTargetControlID = TreeView.GetNodeControlID(parent);
                        DragAndDrop.visualMode = none;
                    }
                }
            }
            Event.current.Use();
            return true;
        }

        public List<int> GetCurrentExpanded()
        {
            if (<>f__am$cache3 == null)
            {
                <>f__am$cache3 = node => node.instanceID;
            }
            return Enumerable.Select<TreeView.Node, int>(from node in this.m_TreeView.m_Data.GetVisibleRows()
                where this.m_TreeView.m_Data.IsExpanded(node)
                select node, <>f__am$cache3).ToList<int>();
        }

        public int GetDropTargetControlID()
        {
            return this.m_DropData.dropTargetControlID;
        }

        public int GetRowMarkerControlID()
        {
            return this.m_DropData.rowMarkerControlID;
        }

        public void RestoreExpanded(List<int> instanceIDs)
        {
            foreach (TreeView.Node node in this.m_TreeView.m_Data.GetVisibleRows())
            {
                this.m_TreeView.m_Data.SetExpanded(node, instanceIDs.Contains(node.instanceID));
            }
        }

        public virtual void StartDrag(TreeView.Node draggedNode, List<int> selectedNodes)
        {
            DragAndDrop.PrepareStartDrag();
            DragAndDrop.objectReferences = ProjectWindowUtil.GetDragAndDropObjects(draggedNode.instanceID, selectedNodes);
            DragAndDrop.paths = ProjectWindowUtil.GetDragAndDropPaths(draggedNode.instanceID, selectedNodes);
            if (DragAndDrop.objectReferences.Length > 1)
            {
                DragAndDrop.StartDrag("<Multiple>");
            }
            else
            {
                DragAndDrop.StartDrag(ObjectNames.GetDragAndDropTitle(InternalEditorUtility.GetObjectFromInstanceID(draggedNode.instanceID)));
            }
        }

        private class DropData
        {
            public int dropTargetControlID;
            public int[] expandedArrayBeforeDrag;
            public double expandItemBeginTimer;
            public int lastControlID;
            public int rowMarkerControlID;
        }
    }
}

